package com.swak.utils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;

import com.swak.converter.CoreConversionService;

/**
 * 类型转换; 并添加一下常用的类型描述
 * 
 * @author 618lf
 */
public class Converters {

	private static final Map<Class<?>, TypeDescriptor> commonTypesCache = new HashMap<>(32);

	private static final Class<?>[] CACHED_COMMON_TYPES = { //
			Date.class, //
			Timestamp.class, //
			LocalDateTime.class, //
			BigDecimal.class, //
			HashMap.class, //
			ArrayList.class //
	};

	static {
		for (Class<?> preCachedClass : CACHED_COMMON_TYPES) {
			commonTypesCache.put(preCachedClass, TypeDescriptor.valueOf(preCachedClass));
		}
	}

	private static TypeDescriptor forObject(@Nullable Object source) {
		return (source != null ? valueOf(source.getClass()) : null);
	}

	private static TypeDescriptor valueOf(@Nullable Class<?> type) {
		if (type == null) {
			type = Object.class;
		}
		TypeDescriptor desc = commonTypesCache.get(type);
		return (desc != null ? desc : TypeDescriptor.valueOf(type));
	}

	/**
	 * 执行转换
	 * 
	 * @param value
	 * @param targetType
	 * @return
	 */
	public static Object doConvert(Object value, Class<?> targetType) {
		TypeDescriptor sourceTypeDesc = forObject(value);
		TypeDescriptor targetDescriptor = valueOf(targetType);
		CoreConversionService conversionService = CoreConversionService.getContext();
		if (conversionService.canConvert(sourceTypeDesc, targetDescriptor)) {
			return conversionService.convert(value, sourceTypeDesc, targetDescriptor);
		}
		return null;
	}
}